package com.autumn.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.autumn.util.convert.AbstractDataConvert;
import com.autumn.util.convert.IDataConvert;
import com.autumn.util.security.Md5Utils;

/**
 * 类型帮助
 * 
 * @author 杨昌国
 *
 *         2017-09-29 14:28:59
 */
public class TypeUtils {

	private static final Map<Class<?>, Integer> BASE_TYPE_MAP = new HashMap<Class<?>, Integer>();

	static {
		/*
		 * 0表示通用，数字>=1,1=表示整数,2=浮点数，11=长整数，12=长实数
		 */
		BASE_TYPE_MAP.put(String.class, 0);
		BASE_TYPE_MAP.put(Time.class, 0);
		BASE_TYPE_MAP.put(TimeSpan.class, 0);
		BASE_TYPE_MAP.put(Date.class, 0);
		BASE_TYPE_MAP.put(Byte.TYPE, 1);
		BASE_TYPE_MAP.put(Byte.class, 1);
		BASE_TYPE_MAP.put(Short.TYPE, 1);
		BASE_TYPE_MAP.put(Short.class, 1);
		BASE_TYPE_MAP.put(Character.TYPE, 0);
		BASE_TYPE_MAP.put(Character.class, 0);
		BASE_TYPE_MAP.put(Integer.TYPE, 1);
		BASE_TYPE_MAP.put(Integer.class, 1);
		BASE_TYPE_MAP.put(Long.TYPE, 1);
		BASE_TYPE_MAP.put(Long.class, 1);
		BASE_TYPE_MAP.put(Float.TYPE, 2);
		BASE_TYPE_MAP.put(Float.class, 2);
		BASE_TYPE_MAP.put(Double.TYPE, 2);
		BASE_TYPE_MAP.put(Double.class, 2);
		BASE_TYPE_MAP.put(Boolean.TYPE, 0);
		BASE_TYPE_MAP.put(Boolean.class, 0);
		BASE_TYPE_MAP.put(java.sql.Time.class, 0);
		BASE_TYPE_MAP.put(java.sql.Date.class, 0);
		BASE_TYPE_MAP.put(java.sql.Timestamp.class, 0);
		BASE_TYPE_MAP.put(BigInteger.class, 11);
		BASE_TYPE_MAP.put(BigDecimal.class, 12);
		BASE_TYPE_MAP.put(Enum.class, 0);
	}

	/**
	 * 获取类的短名称(不含包名)
	 * 
	 * @param type 类型
	 * @return
	 */
	public static String getClassShortName(Class<?> type) {
		ExceptionUtils.checkNotNull(type, "type");
		String[] names = type.getName().split("\\.");
		return names[names.length - 1];
	}

	/**
	 * 是否是基础类型
	 * 
	 * @param type 类型
	 * @return
	 * @author 杨昌国 2017-09-29 14:36:38
	 */
	public static boolean isBaseType(Class<?> type) {
		return BASE_TYPE_MAP.containsKey(type) || Enum.class.isAssignableFrom(type);
	}

	/**
	 * 是否为数字类型
	 * 
	 * @param type 类型
	 * @return byte、Byte、short、Short、int、Integer、long、Long、float、Float、double、Double、BigInteger、BigDecimal
	 *         则为 true, 否则为false
	 * @author 杨昌国 2017-09-29 15:22:00
	 */
	public static boolean isNumberType(Class<?> type) {
		return Number.class.isAssignableFrom(type);
	}

	/**
	 * 是否为整数类型
	 * 
	 * @param type 类型
	 * @return byte、Byte、short、Short、int、Integer、long、Long 则为 true,否则为 false
	 * @author 杨昌国 2017-09-29 15:22:00
	 */
	public static boolean isIntegerType(Class<?> type) {
		Integer value = BASE_TYPE_MAP.get(type);
		if (value == null) {
			return false;
		}
		return value.intValue() == 1;
	}

	/**
	 * 是否为浮点数类型
	 * 
	 * @param type 类型
	 * @return float、Float、double、Double 为 true，否则为 false
	 * @author 杨昌国 2017-09-29 15:22:00
	 */
	public static boolean isFloatType(Class<?> type) {
		Integer value = BASE_TYPE_MAP.get(type);
		if (value == null) {
			return false;
		}
		return value.intValue() == 2;
	}

	/**
	 * 是否是二进制类型
	 * 
	 * @param type 类型
	 * @return
	 * @author 杨昌国 2017-09-29 14:39:27
	 */
	public static boolean isBinaryType(Class<?> type) {
		if (type == null || !type.isArray()) {
			return false;
		}
		return type.equals(byte[].class) || type.equals(Byte[].class);
	}

	/**
	 * 是否是基础或二进制类型
	 * 
	 * @param type 类型
	 * @return
	 * @author 杨昌国 2017-09-29 14:36:38
	 */
	public static boolean isBaseOrBinaryType(Class<?> type) {
		return isBaseType(type) || isBinaryType(type);
	}

	/**
	 * 判断类是否包含特定的注解
	 * 
	 * @param fullClassName
	 * @param annotationClass
	 * @return
	 * @throws ClassNotFoundException
	 */
	public static boolean isAnnotationClass(String fullClassName, Class<? extends Annotation> annotationClass)
			throws ClassNotFoundException {
		if (fullClassName == null || fullClassName.trim().length() == 0) {
			throw new NullPointerException("fullClassName 为 null 或空字符串");
		}
		return isAnnotationClass(Class.forName(fullClassName), annotationClass);
	}

	/**
	 * 判断类是否包含特定的注解
	 * 
	 * @param classType
	 * @param annotationClass
	 * @return
	 * 
	 */
	public static boolean isAnnotationClass(Class<?> classType, Class<? extends Annotation> annotationClass) {
		if (classType == null) {
			throw new NullPointerException("classType 为 null ");
		}
		if (annotationClass == null) {
			throw new NullPointerException("annotationClass 为 null");
		}
		return classType.getAnnotation(annotationClass) != null;
	}

	/**
	 * 对象转换
	 * 
	 * @param targetClass 目标类型
	 * @param source      源
	 * @return
	 * @author 杨昌国 2017-09-30 17:05:13
	 */
	public static Object toObjectConvert(Class<?> targetClass, Object source) {
		if (targetClass == null) {
			return source;
		}
		if (source != null) {
			if (targetClass.isInstance(source)) {
				return source;
			}
			Class<?> sourceClass = source.getClass();
			if (EqualsUtils.equalsPrimitiveClass(targetClass, sourceClass)) {
				return source;
			}
		}
		IDataConvert dataConvert = AbstractDataConvert.getDataConvert(targetClass);
		if (dataConvert == null) {
			return source;
		}
		return dataConvert.convert(targetClass, source);
	}

	/**
	 * 对象转换
	 * 
	 * @param targetClass 目标类型
	 * @param source      源
	 * @return
	 * @author 杨昌国 2017-09-30 17:05:13
	 */
	@SuppressWarnings("unchecked")
	public static <T> T toConvert(Class<T> targetClass, Object source) {
		return (T) toObjectConvert(targetClass, source);
	}

	/**
	 * 是否支持转换
	 * 
	 * @param targetClass 目标类型
	 * @return
	 * @author 杨昌国 2017-09-30 17:11:22
	 */
	public static Object isSupportConvert(Class<?> targetClass) {
		return AbstractDataConvert.getDataConvert(targetClass) != null || Enum.class.isAssignableFrom(targetClass);
	}

	/**
	 * 是否是接口类型
	 * 
	 * @param type 类型
	 * @return
	 *
	 */
	public static boolean isInterface(Class<?> type) {
		int mod = type.getModifiers();
		return Modifier.isInterface(mod);
	}

	/**
	 * 是否是抽象类型
	 * 
	 * @param type 类型
	 * @return
	 *
	 */
	public static boolean isAbstract(Class<?> type) {
		int mod = type.getModifiers();
		return Modifier.isAbstract(mod);
	}

	/**
	 * 是否是公用类型
	 * 
	 * @param type 类型
	 * @return
	 *
	 */
	public static boolean isPublic(Class<?> type) {
		int mod = type.getModifiers();
		return Modifier.isPublic(mod);
	}

	/**
	 * 是否拥有公用的默认构造
	 * 
	 * @param type 类型
	 * @return
	 *
	 */
	public static boolean isDefaultPublicConstructor(Class<?> type) {
		Constructor<?>[] conArray;
		try {
			conArray = type.getConstructors();
			for (Constructor<?> constructor : conArray) {
				if (constructor.getParameterTypes().length == 0) {
					return true;
				}
			}
			return false;
		} catch (SecurityException e) {
			return false;
		}
	}

	/**
	 * 是否是私有类型
	 * 
	 * @param type 类型
	 * @return
	 *
	 */
	public static boolean isPrivate(Class<?> type) {
		int mod = type.getModifiers();
		return Modifier.isPrivate(mod);
	}

	/**
	 * 是否是 protected 类型
	 * 
	 * @param type 类型
	 * @return
	 *
	 */
	public static boolean isProtected(Class<?> type) {
		int mod = type.getModifiers();
		return Modifier.isProtected(mod);
	}

	/**
	 * 是否是 final 类型(不可继承)
	 * 
	 * @param type 类型
	 * @return
	 *
	 */
	public static boolean isFinal(Class<?> type) {
		int mod = type.getModifiers();
		return Modifier.isFinal(mod);
	}

	/**
	 * 是否是静态类型
	 * 
	 * @param type 类型
	 * @return
	 *
	 */
	public static boolean isStatic(Class<?> type) {
		int mod = type.getModifiers();
		return Modifier.isStatic(mod);
	}

	/**
	 * 加载类名称
	 * 
	 * @param className 类名称
	 * @return 不存在则返回 null
	 */
	public static Class<?> forName(String className) {
		ExceptionUtils.checkNotNull(className, "className");
		try {
			return Class.forName(className);
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * 是否存在类名称
	 * 
	 * @param className 类名称类名称
	 * @return
	 */
	public static boolean isExistClassName(String className) {
		return forName(className) != null;
	}

	/**
	 * 获取所有接口
	 * 
	 * @param type
	 * @return
	 */
	public static Set<Class<?>> getInterfaces(Class<?> type) {
		ExceptionUtils.checkNotNull(type, "type");
		Set<Class<?>> types = new HashSet<>();
		Class<?>[] interfaces = type.getInterfaces();
		for (Class<?> interfaceType : interfaces) {
			types.add(interfaceType);
			types.addAll(getInterfaces(interfaceType));
		}
		return types;
	}

	/**
	 * 比较两个类型是否完成相同
	 * 
	 * @param leftTypes  右边类型集合
	 * @param rigthTypes 右边类型集合
	 * @return
	 */
	public static boolean equalsTypes(Class<?>[] leftTypes, Class<?>[] rigthTypes) {
		if (leftTypes == null) {
			leftTypes = new Class<?>[0];
		}
		if (rigthTypes == null) {
			rigthTypes = new Class<?>[0];
		}
		if (leftTypes.length != rigthTypes.length) {
			return false;
		}
		for (int i = 0; i < leftTypes.length; i++) {
			if (!leftTypes[i].equals(rigthTypes[i])) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 获取8位整数二进制的值
	 * 
	 * @param value 值
	 * @return
	 */
	public static byte[] getRawValue(byte value) {
		byte[] result = new byte[1];
		result[0] = value;
		return result;
	}

	/**
	 * 获取二进制的8整数值
	 * 
	 * @param value 值
	 * @return
	 */
	public static byte getByteValue(byte[] bytes) {
		if (bytes == null || bytes.length == 0) {
			return 0;
		}
		return bytes[0];
	}

	/**
	 * 获取16位整数二进制的值
	 * 
	 * @param value 值
	 * @return
	 */
	public static byte[] getRawValue(short value) {
		ByteBuffer buffer = ByteBuffer.allocate(2);
		buffer.putShort(0, value);
		return buffer.array();
	}

	/**
	 * 获取二进制的16整数值
	 * 
	 * @param value 值
	 * @return
	 */
	public static short getShortValue(byte[] bytes) {
		if (bytes == null) {
			return 0;
		}
		ByteBuffer buffer = ByteBuffer.allocate(2);
		buffer.put(bytes, 0, bytes.length);
		buffer.flip();
		return buffer.getShort();
	}

	/**
	 * 获取32位整数二进制的值
	 * 
	 * @param value 值
	 * @return
	 */
	public static byte[] getRawValue(int value) {
		ByteBuffer buffer = ByteBuffer.allocate(4);
		buffer.putInt(0, value);
		return buffer.array();
	}

	/**
	 * 获取二进制的32整数值
	 * 
	 * @param value 值
	 * @return
	 */
	public static int getIntegerValue(byte[] bytes) {
		if (bytes == null) {
			return 0;
		}
		ByteBuffer buffer = ByteBuffer.allocate(4);
		buffer.put(bytes, 0, bytes.length);
		buffer.flip();
		return buffer.getInt();
	}

	/**
	 * 获取64位整数二进制的值
	 * 
	 * @param value 值
	 * @return
	 */
	public static byte[] getRawValue(long value) {
		ByteBuffer buffer = ByteBuffer.allocate(8);
		buffer.putLong(0, value);
		return buffer.array();
	}

	/**
	 * 获取二进制的64整数值
	 * 
	 * @param bytes
	 * @return
	 */
	public static long getLongValue(byte[] bytes) {
		if (bytes == null) {
			return 0L;
		}
		ByteBuffer buffer = ByteBuffer.allocate(8);
		buffer.put(bytes, 0, bytes.length);
		buffer.flip();
		return buffer.getLong();
	}

	private final static int BIG_INTEGER_LENGTH = 33;

	/**
	 * 大数字转换字节流（字节数组）型数据
	 * 
	 * @param n
	 * @return
	 */
	public static byte[] getRawValue(BigInteger n) {
		byte tmpd[] = (byte[]) null;
		if (n == null) {
			return null;
		}
		int len = BIG_INTEGER_LENGTH - 1;
		if (n.toByteArray().length == BIG_INTEGER_LENGTH) {
			tmpd = new byte[len];
			System.arraycopy(n.toByteArray(), 1, tmpd, 0, len);
		} else if (n.toByteArray().length == len) {
			tmpd = n.toByteArray();
		} else {
			tmpd = new byte[len];
			for (int i = 0; i < len - n.toByteArray().length; i++) {
				tmpd[i] = 0;
			}
			System.arraycopy(n.toByteArray(), 0, tmpd, len - n.toByteArray().length, n.toByteArray().length);
		}
		return tmpd;
	}

	/**
	 * 换字节流（字节数组）型数据转大数字
	 * 
	 * @param b
	 * @return
	 */
	public static BigInteger getBigInteger(byte[] b) {
		if (b[0] < 0) {
			byte[] temp = new byte[b.length + 1];
			temp[0] = 0;
			System.arraycopy(b, 0, temp, 1, b.length);
			return new BigInteger(temp);
		}
		return new BigInteger(b);
	}

	/**
	 * 获取 float 二进制的值
	 * 
	 * @param value 值
	 * @return
	 */
	public static byte[] getRawValue(float value) {
		ByteBuffer buffer = ByteBuffer.allocate(4);
		buffer.putFloat(0, value);
		return buffer.array();
	}

	/**
	 * 获取二进制的 float 值
	 * 
	 * @param bytes
	 * @return
	 */
	public static float getFloatValue(byte[] bytes) {
		if (bytes == null) {
			return 0L;
		}
		ByteBuffer buffer = ByteBuffer.allocate(4);
		buffer.put(bytes, 0, bytes.length);
		buffer.flip();
		return buffer.getFloat();
	}

	/**
	 * 获取 double 二进制的值
	 * 
	 * @param value 值
	 * @return
	 */
	public static byte[] getRawValue(double value) {
		ByteBuffer buffer = ByteBuffer.allocate(8);
		buffer.putDouble(0, value);
		return buffer.array();
	}

	/**
	 * 获取二进制的 double 值
	 * 
	 * @param bytes
	 * @return
	 */
	public static double getDoubleValue(byte[] bytes) {
		if (bytes == null) {
			return 0L;
		}
		ByteBuffer buffer = ByteBuffer.allocate(8);
		buffer.put(bytes, 0, bytes.length);
		buffer.flip();
		return buffer.getDouble();
	}

	/**
	 * 获取 char 二进制的值
	 * 
	 * @param value 值
	 * @return
	 */
	public static byte[] getRawValue(char value) {
		ByteBuffer buffer = ByteBuffer.allocate(2);
		buffer.putChar(0, value);
		return buffer.array();
	}

	/**
	 * 获取二进制的 char 值
	 * 
	 * @param bytes
	 * @return
	 */
	public static char getCharValue(byte[] bytes) {
		if (bytes == null) {
			return '0';
		}
		ByteBuffer buffer = ByteBuffer.allocate(2);
		buffer.put(bytes, 0, bytes.length);
		buffer.flip();
		return buffer.getChar();
	}

	/**
	 * 根据字节数组获得值(十六进制数字)
	 * 
	 * @param bytes
	 * @return
	 */
	public static String getHexString(byte[] bytes) {
		return getHexString(bytes, false);
	}

	/**
	 * 根据字节数组获得值(十六进制数字)
	 * 
	 * @param bytes
	 * @param upperCase 是否转换为大写
	 * @return
	 */
	public static String getHexString(byte[] bytes, boolean upperCase) {
		String ret = "";
		for (int i = 0; i < bytes.length; i++) {
			ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1);
		}
		return upperCase ? ret.toUpperCase() : ret;
	}

	/**
	 * 16进制转换为数组
	 * 
	 * @param hexString 16进制字符窜
	 * 
	 * @return byte[] 返回数组
	 */
	public static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
		}
		return d;
	}

	/**
	 * Convert char to byte
	 * 
	 * @param c char
	 * @return byte
	 */
	public static byte charToByte(char c) {
		return (byte) Md5Utils.HEXDIGITS_STRING_UPPER.indexOf(c);
	}

}
